package com.scidpro;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.scid.database.ScidProviderMetaData;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.text.Html;
import android.text.InputType;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.scidpro.chessok.ImportChessOkActivity;
import com.scidpro.dialog.MoveListDialog;
import com.scidpro.engine.EngineManager;
import com.scidpro.engine.EngineManager.EngineChangeEvent;
import com.scidpro.gamelogic.ChessController;
import com.scidpro.gamelogic.ChessParseError;
import com.scidpro.gamelogic.Move;
import com.scidpro.gamelogic.Position;
import com.scidpro.gamelogic.TextIO;
import com.scidpro.twic.ImportTwicActivity;

@Deprecated
public class ScidAndroidActivity extends Activity implements GUIInterface, IClipboardChangedListener, IDownloadCallback {

	private ChessBoard cb;
	private EngineManager engineManager;
	private ChessController ctrl = null;
	private boolean mShowThinking;
	private boolean mShowBookHints;
	private int maxNumArrows;
	private GameMode gameMode = new GameMode(GameMode.TWO_PLAYERS);
	private boolean boardFlipped = false;
	private boolean autoSwapSides = false;
	private boolean reloadGameList = false;

	private TextView status;
	private ScrollView moveListScroll;
	private TextView moveList;
	private TextView whitePlayer;
	private TextView blackPlayer;
	private TextView gameNo;

	private ImageButton nextButton;
	private ImageButton previousButton;
	private ImageButton nextGameButton;
	private ImageButton previousGameButton;
	private ImageButton gameModeButton;
	private ImageButton favoriteGameButton;

	private View help;

	SharedPreferences settings;

	public static final String SCID_DIRECTORY = "LearnChess";
	private PGNOptions pgnOptions = new PGNOptions();

	PgnScreenText gameTextListener;
	private String myPlayerNames = "";
	private String lastWhitePlayerName = "";
	private String lastBlackPlayerName = "";
	private String lastEndOfVariation = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		File scidFileDir = new File(Environment.getExternalStorageDirectory() + File.separator + SCID_DIRECTORY);
		if (!scidFileDir.exists()) {
			scidFileDir.mkdirs();
		}
		checkUciEngine();
		engineManager = EngineManager.getInstance();
		engineManager.setContext(this);
		settings = PreferenceManager.getDefaultSharedPreferences(this);
		settings.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
			@Override
			public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
				readPrefs();
				setGameMode();
			}
		});

		// do not use custom titles on Honeycomb and above - don't work with
		// the Holo Theme
		initUI(Build.VERSION.SDK_INT < 11);
		if (Build.VERSION.SDK_INT >= 11) {
			VersionHelper.registerClipChangedListener(this);
		}

		gameTextListener = new PgnScreenText(pgnOptions);
		ctrl = new ChessController(this, gameTextListener, pgnOptions);
		getScidAppContext().setController(ctrl);
		ctrl.newGame(new GameMode(GameMode.TWO_PLAYERS));
		readPrefs();
		ctrl.newGame(gameMode);

		int gameNo = settings.getInt("currentGameNo", 0);
		Cursor cursor = getCursor();
		if (cursor != null && cursor.moveToPosition(gameNo)) {
			this.getScidAppContext().setCurrentGameNo(gameNo);
		}

		byte[] data = null;
		if (savedInstanceState != null) {
			data = savedInstanceState.getByteArray("gameState");
			getScidAppContext().setFavorite(savedInstanceState.getBoolean("isFavorite"));
			getScidAppContext().setDeleted(savedInstanceState.getBoolean("isDeleted"));
		} else {
			String dataStr = settings.getString("gameState", null);
			if (dataStr != null) {
				data = strToByteArr(dataStr);
			}
			getScidAppContext().setFavorite(settings.getBoolean("isFavorite", false));
			getScidAppContext().setDeleted(settings.getBoolean("isDeleted", false));
		}
		if (data != null) {
			ctrl.fromByteArray(data);
		}

		ctrl.setGuiPaused(true);
		ctrl.setGuiPaused(false);
		ctrl.startGame();
		setFav();

		registerForContextMenu(moveListScroll);
	}

	@Override
	protected void onDestroy() {
		if (ctrl != null) {
			ctrl.shutdownEngine();
		}
		super.onDestroy();
	}

	@Override
	protected void onResume() {
		getIntentData();
		if (ctrl != null) {
			ctrl.setGuiPaused(false);
		}
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
		boolean auto = prefs.getBoolean("mode", false);
		if (auto) {
			startAutoPlay();
		}
		super.onResume();
	}

	@Override
	protected void onPause() {
		if (ctrl != null) {
			ctrl.setGuiPaused(true);
			saveGameState();
			ctrl.shutdownEngine();
		}
		stopAutoPlay();
		super.onPause();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		if (ctrl != null) {
			byte[] data = ctrl.toByteArray();
			outState.putByteArray("gameState", data);
		}
		outState.putBoolean("isFavorite", getScidAppContext().isFavorite());
		outState.putBoolean("isDeleted", getScidAppContext().isDeleted());
	}

	private final void initUI(boolean initTitle) {
		if (initTitle) {
			requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
		}

		setContentView(R.layout.main);

		if (initTitle) {
			getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title);
			whitePlayer = (TextView) findViewById(R.id.white_player);
			blackPlayer = (TextView) findViewById(R.id.black_player);
			gameNo = (TextView) findViewById(R.id.gameNo);
		}

		status = (TextView) findViewById(R.id.status);
		status.setFocusable(false);

		moveListScroll = (ScrollView) findViewById(R.id.moveListScrollView);
		moveListScroll.setFocusable(false);

		moveList = (TextView) findViewById(R.id.moveList);
		moveList.setMovementMethod(LinkMovementMethod.getInstance());
		moveList.setFocusable(false);
		moveList.setTextColor(moveList.getTextColors().getDefaultColor());
		moveList.setLinkTextColor(moveList.getTextColors().getDefaultColor());

		cb = (ChessBoard) findViewById(R.id.chessboard);
		cb.setFocusable(false);
		cb.setClickable(true);
		cb.setOnTouchListener(new GestureListener(this, new GestureListener.OnSwipeListener() {
			@Override
			public void onSwipe() {
				flipBoard();
			}
		}));

		boolean auto = settings.getBoolean("mode", false);

		gameModeButton = (ImageButton) findViewById(R.id.game_mode_button);
		gameModeButton.setImageResource(auto ? R.drawable.pause : R.drawable.play);
		gameModeButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ScidAndroidActivity.this);
				boolean auto = prefs.getBoolean("mode", false);
				Editor e = prefs.edit();
				e.putBoolean("mode", !auto);
				e.commit();

				gameModeButton.setImageResource(!auto ? R.drawable.pause : R.drawable.play);

				if (!auto) {
					startAutoPlay();
				} else {
					stopAutoPlay();
				}
			}
		});

		favoriteGameButton = (ImageButton) findViewById(R.id.favorite_game);
		favoriteGameButton.setImageResource(this.getScidAppContext().isFavorite() ? R.drawable.fav : R.drawable.notfav);
		favoriteGameButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				updateFavorite();
			}
		});

		nextButton = (ImageButton) findViewById(R.id.next_move);
		nextButton.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {
				ctrl.gotoMove(999);
				lastEndOfVariation = null;
				return true;
			}
		});

		previousButton = (ImageButton) findViewById(R.id.previous_move);
		previousButton.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {
				ctrl.gotoMove(0);
				lastEndOfVariation = null;
				moveListScroll.fullScroll(View.FOCUS_UP);
				return true;
			}
		});

		nextGameButton = (ImageButton) findViewById(R.id.next_game);
		nextGameButton.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {
				Cursor cursor = getScidAppContext().getGamesCursor();
				if (cursor == null) {
					cursor = getCursor();
				}
				if (cursor != null) {
					startManagingCursor(cursor);
					if (cursor.moveToLast()) {
						setPgnFromCursor(cursor);
					}
				}
				return true;
			}
		});

		previousGameButton = (ImageButton) findViewById(R.id.previous_game);
		previousGameButton.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {
				Cursor cursor = getScidAppContext().getGamesCursor();
				if (cursor == null) {
					cursor = getCursor();
				}
				if (cursor != null) {
					startManagingCursor(cursor);
					if (cursor.moveToFirst()) {
						setPgnFromCursor(cursor);
					}
				}
				return true;
			}
		});

		boolean firstStart = settings.getBoolean("show_help", true);

		help = findViewById(R.id.help_screeen);
		help.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				help.setVisibility(View.GONE);

				SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ScidAndroidActivity.this);
				Editor e = prefs.edit();
				e.putBoolean("show_help", false);
				e.commit();
			}
		});
		help.setVisibility(firstStart ? View.VISIBLE : View.GONE);
	}

	private void checkUciEngine() {
		// check if engine exists in /data/data/com.scidpro
		File engine = new File(EngineManager.getDefaultEngine().getExecutablePath());
		if (engine.exists()) {
			try {
				String cmd[] = { "chmod", "744", engine.getAbsolutePath() };
				Process process = Runtime.getRuntime().exec(cmd);
				try {
					process.waitFor();
					Log.d("SCID", "chmod 744 " + engine.getAbsolutePath());
				} catch (InterruptedException e) {
					Log.e("SCID", e.getMessage(), e);
				}
			} catch (IOException e) {
				Log.e("SCID", e.getMessage(), e);
			}
		} else {

			Log.d("SCID", "Engine is missing from data. Intializing...");
			try {
				InputStream istream = getAssets().open(engine.getName());
				FileOutputStream fout = new FileOutputStream(engine.getAbsolutePath());
				byte[] b = new byte[1024];
				int noOfBytes = 0;
				while ((noOfBytes = istream.read(b)) != -1) {
					fout.write(b, 0, noOfBytes);
				}
				istream.close();
				fout.close();
				Log.d("SCID", engine.getName() + " copied to /data/data/com.scidpro/");
				try {
					String cmd[] = { "chmod", "744", engine.getAbsolutePath() };
					Process process = Runtime.getRuntime().exec(cmd);
					try {
						process.waitFor();
						Log.d("SCID", "chmod 744 " + engine.getAbsolutePath());
					} catch (InterruptedException e) {
						Log.e("SCID", e.getMessage(), e);
					}
				} catch (IOException e) {
					Log.e("SCID", e.getMessage(), e);
				}
			} catch (IOException e) {
				Log.e("SCID", e.getMessage(), e);
			}
		}
	}

	public void onNextGameClick(View view) {
		Cursor cursor = this.getScidAppContext().getGamesCursor();
		if (cursor == null) {
			cursor = this.getCursor();
		}
		if (cursor != null) {
			lastEndOfVariation = null;
			startManagingCursor(cursor);
			boolean result = false;
			if (cursor.isBeforeFirst()) {
				result = cursor.moveToFirst();
			} else {
				result = cursor.moveToNext();
			}
			if (result) {
				setPgnFromCursor(cursor);
			}
		}
	}

	private void setPgnFromCursor(Cursor cursor) {
		Log.d("SCID", "getting cursor");
		this.getScidAppContext().setCurrentGameNo(cursor.getInt(cursor.getColumnIndex(ScidProviderMetaData.ScidMetaData._ID)));
		boolean isFavorite = Boolean.parseBoolean(cursor.getString(cursor.getColumnIndex(ScidProviderMetaData.ScidMetaData.IS_FAVORITE)));
		boolean isDeleted = Boolean.parseBoolean(cursor.getString(cursor.getColumnIndex(ScidProviderMetaData.ScidMetaData.IS_DELETED)));
		Log.d("SCID", "isFavorite=" + isFavorite);
		Log.d("SCID", "isDeleted=" + isDeleted);
		this.getScidAppContext().setFavorite(isFavorite);
		this.getScidAppContext().setDeleted(isDeleted);
		setFav();

		saveCurrentGameNo();
		Log.d("SCID", "loading pgn for game " + this.getScidAppContext().getCurrentGameNo());
		String pgn = cursor.getString(cursor.getColumnIndex(ScidProviderMetaData.ScidMetaData.PGN));
		Log.d("SCID", "pgn length=" + pgn.length());
		if (pgn != null && pgn.length() > 0) {
			try {
				ctrl.setPGN(pgn);
				Log.d("SCID", "finished setPGN");
				int moveNo = cursor.getInt(cursor.getColumnIndex(ScidProviderMetaData.ScidMetaData.CURRENT_PLY));
				if (moveNo > 0) {
					ctrl.gotoHalfMove(moveNo);
				}
				if (gameMode.studyMode()) {
					// auto-flip board to the side which has the move
					boardFlipped = !cb.pos.whiteMove;
					cb.setFlipped(boardFlipped);
				}
				saveGameState();
			} catch (ChessParseError e) {
				Log.i("SCID", "ChessParseError", e);
				Toast.makeText(getApplicationContext(), "Parse error " + e.getMessage(), Toast.LENGTH_SHORT).show();
			}
		}
		updateMenu();
	}

	private void setFav() {
		if (favoriteGameButton != null) {
			boolean isFav = this.getScidAppContext().isFavorite();
			favoriteGameButton.setImageResource(isFav ? R.drawable.fav : R.drawable.notfav);
		}
	}

	/**
	 * Check white and black player name if it corresponds to myPlayerNames and
	 * flip board if necessary
	 */
	private void flipBoardForPlayerNames(String white, String black) {
		if (!white.equalsIgnoreCase(this.lastWhitePlayerName) || !black.equalsIgnoreCase(this.lastBlackPlayerName)) {
			this.lastWhitePlayerName = white;
			this.lastBlackPlayerName = black;
			String[] names = myPlayerNames.split("\\n");
			for (int i = 0; i < names.length; i++) {
				String playerName = names[i].trim();
				if (white.equalsIgnoreCase(playerName) && boardFlipped) {
					boardFlipped = !boardFlipped;
					setBoardFlip();
					break;
				} else if (black.equalsIgnoreCase(playerName) && !boardFlipped) {
					boardFlipped = !boardFlipped;
					setBoardFlip();
					break;
				}
			}
		}
	}

	public void onPreviousGameClick(View view) {
		Cursor cursor = this.getScidAppContext().getGamesCursor();
		if (cursor == null) {
			cursor = this.getCursor();
		}
		if (cursor != null) {
			startManagingCursor(cursor);
			if (cursor.isAfterLast()) {
				cursor.moveToLast();
			}
			if (cursor.getPosition() > 0 && cursor.moveToPrevious()) {
				setPgnFromCursor(cursor);
			}
			lastEndOfVariation = null;
		}
	}

	public void onNextMoveClick(View view) {
		if (ctrl.canRedoMove()) {
			ctrl.redoMove();
		} else {
			String currentPosition = ctrl.getFEN();
			if (lastEndOfVariation == null || !lastEndOfVariation.equals(currentPosition)) {
				lastEndOfVariation = currentPosition;
				Toast.makeText(getApplicationContext(), getText(R.string.end_of_variation), Toast.LENGTH_SHORT).show();
			}
		}
	}

	public void onPreviousMoveClick(View view) {
		ctrl.undoMove();
		lastEndOfVariation = null;
	}

	public void flipBoard() {
		boardFlipped = !boardFlipped;
		Editor editor = settings.edit();
		editor.putBoolean("boardFlipped", boardFlipped);
		editor.commit();
		setBoardFlip();
	}

	private Timer timer;

	public void startAutoPlay() {
		if (timer == null) {
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
			float interval = prefs.getInt("moveInterval", 1);

			if (interval == 0) {
				interval = 0.5f;
			}

			timer = new Timer();
			timer.schedule(new TimerTask() {
				@Override
				public void run() {
					runOnUiThread(new Runnable() {
						public void run() {
							nextMove();
						}
					});
				}
			}, 0, (long) (interval * 1000));

			gameModeButton.setImageResource(R.drawable.pause);

			boolean keepScreenOn = prefs.getBoolean("keepScreenOn", true);
			cb.setKeepScreenOn(keepScreenOn);
		} else {
			stopAutoPlay();
			startAutoPlay();
		}
	}

	public void stopAutoPlay() {
		if (timer != null) {
			timer.cancel();
			timer.purge();
			timer = null;

			gameModeButton.setImageResource(R.drawable.play);
		}

		cb.setKeepScreenOn(false);
	}

	private void nextMove() {
		if (ctrl.canRedoMove()) {
			ctrl.redoMove();
		} else {
			nextGame();
		}
	}

	private void nextGame() {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ScidAndroidActivity.this);
		boolean playNext = prefs.getBoolean("automaticalyPlayNextGame", true);

		if (playNext) {
			Cursor cursor = getScidAppContext().getGamesCursor();
			if (cursor == null) {
				cursor = getCursor();
			}
			if (cursor != null) {
				lastEndOfVariation = null;
				startManagingCursor(cursor);
				boolean result = false;
				if (cursor.isBeforeFirst() || cursor.isLast()) {
					result = cursor.moveToFirst();
				} else {
					result = cursor.moveToNext();
				}
				if (result) {
					stopAutoPlay();
					float interval = prefs.getInt("gameInterval", 1);
					final Cursor finalCursor = cursor;
					new Timer().schedule(new TimerTask() {
						@Override
						public void run() {
							runOnUiThread(new Runnable() {
								public void run() {
									setPgnFromCursor(finalCursor);
									startAutoPlay();
								}
							});
						}
					}, (long) (interval * 1000));
				}
			}
		} else {
			Editor e = prefs.edit();
			e.putBoolean("mode", false);
			e.commit();

			stopAutoPlay();
		}
	}

	private final byte[] strToByteArr(String str) {
		int nBytes = str.length() / 2;
		byte[] ret = new byte[nBytes];
		for (int i = 0; i < nBytes; i++) {
			int c1 = str.charAt(i * 2) - 'A';
			int c2 = str.charAt(i * 2 + 1) - 'A';
			ret[i] = (byte) (c1 * 16 + c2);
		}
		return ret;
	}

	private final String byteArrToString(byte[] data) {
		StringBuilder ret = new StringBuilder(32768);
		int nBytes = data.length;
		for (int i = 0; i < nBytes; i++) {
			int b = data[i];
			if (b < 0) {
				b += 256;
			}
			char c1 = (char) ('A' + (b / 16));
			char c2 = (char) ('A' + (b & 15));
			ret.append(c1);
			ret.append(c2);
		}
		return ret.toString();
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		ChessBoard oldCB = cb;
		String statusStr = status.getText().toString();
		if (statusStr.startsWith("DELETED ")) {
			statusStr = statusStr.substring(8);
		}
		initUI(false);
		readPrefs();
		cb.cursorX = oldCB.cursorX;
		cb.cursorY = oldCB.cursorY;
		cb.cursorVisible = oldCB.cursorVisible;
		cb.setPosition(oldCB.pos);
		cb.setFlipped(oldCB.flipped);
		cb.oneTouchMoves = oldCB.oneTouchMoves;
		setSelection(oldCB.selectedSquare);
		updateThinkingInfo();
		setStatusString(statusStr);
		moveListUpdated();
		setFav();
	}

	/**
	 * Called after onResume to support the registered *.pgn extension
	 */
	private void getIntentData() {
		Uri data = getIntent().getData();
		if (data != null) {
			Tools.processUri(this, data, RESULT_PGN_IMPORT);
			// the data was handled, set it to null to not enter this again in
			// onResume()
			getIntent().setData(null);
		}
	}

	private void saveGameState() {
		byte[] data = ctrl.toByteArray();
		Editor editor = settings.edit();
		String dataStr = byteArrToString(data);
		editor.putString("gameState", dataStr);
		editor.putBoolean("isFavorite", getScidAppContext().isFavorite());
		editor.putBoolean("isDeleted", getScidAppContext().isDeleted());
		editor.commit();
	}

	private final void readPrefs() {
		boardFlipped = settings.getBoolean("boardFlipped", false);
		this.myPlayerNames = settings.getString("playerNames", "");
		setBoardFlip();
		cb.oneTouchMoves = settings.getBoolean("oneTouchMoves", false);
		mShowThinking = settings.getBoolean("showThinking", false);
		String tmp = settings.getString("thinkingArrows", "6");
		maxNumArrows = Integer.parseInt(tmp);
		mShowBookHints = settings.getBoolean("bookHints", false);
		gameMode = new GameMode(settings.getInt("gameMode", GameMode.TWO_PLAYERS));
		ctrl.setTimeLimit(300000, 60, 0);

		setFullScreenMode(true);

		tmp = settings.getString("fontSize", "12");
		int fontSize = Integer.parseInt(tmp);
		status.setTextSize(fontSize);
		moveList.setTextSize(fontSize);

		pgnOptions.view.variations = true;
		pgnOptions.view.comments = true;
		pgnOptions.view.nag = true;
		pgnOptions.view.headers = false;
		pgnOptions.view.allMoves = true;
		String moveDisplayString = settings.getString("moveDisplay", "0");
		int moveDisplay = Integer.parseInt(moveDisplayString);
		if (moveDisplay != 0) {
			pgnOptions.view.allMoves = false;
		}
		pgnOptions.imp.variations = true;
		pgnOptions.imp.comments = true;
		pgnOptions.imp.nag = true;
		pgnOptions.exp.variations = true;
		pgnOptions.exp.comments = true;
		pgnOptions.exp.nag = true;
		pgnOptions.exp.playerAction = false;
		pgnOptions.exp.clockInfo = false;

		ColorTheme.instance().readColors(settings);
		cb.setColors();

		String engineName = settings.getString("analysisEngine", EngineManager.getDefaultEngine().getName());
		engineManager.setCurrentEngineName(engineName);

		final String currentScidFile = settings.getString("currentScidFile", "");
		if (currentScidFile.length() > 0) {
			this.getScidAppContext().setCurrentFileName(Tools.stripExtension(currentScidFile));
		}

		gameTextListener.clear();
		ctrl.prefsChanged();
	}

	private final void setFullScreenMode(boolean fullScreenMode) {
		WindowManager.LayoutParams attrs = getWindow().getAttributes();
		if (fullScreenMode) {
			attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
		} else {
			attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
		}
		getWindow().setAttributes(attrs);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.options_menu, menu);
		return true;
	}

	static private final int RESULT_EDITBOARD = 0;
	static private final int RESULT_SETTINGS = 1;
	static private final int RESULT_SEARCH = 2;
	static private final int RESULT_PGN_FILEDIALOG = 3;
	static private final int RESULT_GAMELIST = 4;
	static private final int RESULT_PGN_IMPORT = 5;
	static private final int RESULT_TWIC_IMPORT = 6;
	static private final int RESULT_LOAD_SCID_FILE = 7;
	static private final int RESULT_ADD_ENGINE = 8;
	static private final int RESULT_REMOVE_ENGINE = 9;
	static private final int RESULT_SAVE_GAME = 10;
	static private final int RESULT_PGN_FILE_IMPORT = 11;

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {

		case R.id.item_all_books_list: {
			Intent i = new Intent(ScidAndroidActivity.this, AllBooksListActivity.class);
			startActivity(i);
			return true;
		}
		case R.id.item_my_books_list: {
			Intent i = new Intent(ScidAndroidActivity.this, MyBooksListActivity.class);
			startActivityForResult(i, RESULT_LOAD_SCID_FILE);
			updateMenu();
			return true;
		}
		case R.id.item_gamelist: {
			Intent i = new Intent(ScidAndroidActivity.this, GameListActivity.class);
			i.setAction("" + reloadGameList);
			startActivityForResult(i, RESULT_GAMELIST);
			reloadGameList = false;
			return true;
		}
		case R.id.item_help: {
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ScidAndroidActivity.this);
			Editor e = prefs.edit();
			e.putBoolean("show_help", true);
			e.commit();

			help.setVisibility(View.VISIBLE);
			return true;
		}
		case R.id.item_settings: {
			Intent i = new Intent(ScidAndroidActivity.this, Preferences.class);
			i.putExtra(Preferences.DATA_ENGINE_NAMES, engineManager.getEngineNames(true));
			i.putExtra(Preferences.DATA_ENGINE_NAME, engineManager.getCurrentEngineName());
			startActivityForResult(i, RESULT_SETTINGS);
			return true;
		}
		case R.id.item_import_pgn: {
			removeDialog(IMPORT_PGN_DIALOG);
			showDialog(IMPORT_PGN_DIALOG);
			updateMenu();
			return true;
		}
		}
		return false;
	}

	private void updateFavorite() {
		if (getScidAppContext().isFavorite()) {
			updateFavoriteFlag(false, getString(R.string.remove_favorites_success), getString(R.string.remove_favorites_failure));
		} else {
			updateFavoriteFlag(true, getString(R.string.add_favorites_success), getString(R.string.add_favorites_failure));
		}
		updateMenu();
	}

	private void updateMenu() {
		if (Build.VERSION.SDK_INT >= 11) {
			VersionHelper.refreshActionBarMenu(this);
		}
	}

	// private void saveGame() {
	// Intent i = new Intent(ScidAndroidActivity.this, SaveGameActivity.class);
	// startActivityForResult(i, RESULT_SAVE_GAME);
	// }

	// private void setStudyMode() {
	// if (gameMode.studyMode()) {
	// gameMode = new GameMode(GameMode.TWO_PLAYERS);
	// } else {
	// gameMode = new GameMode(GameMode.STUDY_MODE);
	// }
	// updateThinkingInfo();
	// moveListUpdated();
	// setGameMode();
	// Toast.makeText(
	// getApplicationContext(),
	// gameMode.studyMode() ? R.string.study_mode_enabled
	// : R.string.study_mode_disabled, Toast.LENGTH_SHORT)
	// .show();
	// }
	//
	// private void setAnalysisMode() {
	// if (gameMode.analysisMode()) {
	// ctrl.shutdownEngine();
	// gameMode = new GameMode(GameMode.TWO_PLAYERS);
	// moveListUpdated();
	// setGameMode();
	// showAnalysisModeInfo();
	// Tools.setKeepScreenOn(this, false);
	// } else {
	// gameMode = new GameMode(GameMode.ANALYSIS);
	// startAnalysis();
	// }
	// }
	//
	// private void showAnalysisModeInfo() {
	// if (gameMode.analysisMode()) {
	// String msg = getApplicationContext().getString(
	// R.string.analysis_mode_enabled,
	// engineManager.getCurrentEngineName());
	// Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT)
	// .show();
	// } else {
	// Toast.makeText(getApplicationContext(),
	// R.string.analysis_mode_disabled, Toast.LENGTH_SHORT).show();
	// }
	// }
	//
	// private void startAnalysis() {
	// if (!ctrl.hasEngineStarted()) {
	// moveList.setText(R.string.initializing_engine);
	// new StartEngineTask().execute(this, ctrl,
	// engineManager.getCurrentEngine());
	// } else {
	// onFinishStartAnalysis();
	// }
	// }
	//
	// protected void onFinishStartAnalysis() {
	// showAnalysisModeInfo();
	// moveListUpdated();
	// setGameMode();
	// ctrl.startGame();
	// updateThinkingInfo();
	// Tools.setKeepScreenOn(this, true);
	// }

	private boolean setGameMode() {
		boolean changed = false;
		if (ctrl.setGameMode(gameMode)) {
			changed = true;
			Editor editor = settings.edit();
			editor.putInt("gameMode", gameMode.getMode());
			editor.commit();
		}
		return changed;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case RESULT_LOAD_SCID_FILE:
			if (resultCode == RESULT_OK && data != null) {
				String fileName = data.getAction();
				if (fileName != null) {
					final String currentScidFile = settings.getString("currentScidFile", "");
					int gameNo = 0;
					if (fileName.equals(currentScidFile)) {
						gameNo = settings.getInt("currentGameNo", 0);
					}
					loadScidFile(fileName, gameNo);
				}
			}
			break;
		case RESULT_SETTINGS:
			readPrefs();
			String theme = settings.getString("colorTheme", "0");
			ColorTheme.instance().setTheme(settings, Integer.parseInt(theme));
			cb.setColors();
			setGameMode();
			break;
		case RESULT_EDITBOARD:
			if (resultCode == RESULT_OK && data != null) {
				try {
					String fen = data.getAction();
					ctrl.setFENOrPGN(fen);
				} catch (ChessParseError e) {
					Log.d("SCID", "ChessParseError", e);
				}
			}
			break;
		case RESULT_SEARCH:
			if (resultCode == RESULT_OK) {
				Cursor cursor = this.getScidAppContext().getGamesCursor();
				if (cursor == null) {
					cursor = this.getCursor();
				}
				if (cursor != null) {
					startManagingCursor(cursor);
					setPgnFromCursor(cursor);
				}
			} else if (resultCode == RESULT_FIRST_USER) {
				resetFilter();
			}
			break;
		case RESULT_GAMELIST:
			if (resultCode == RESULT_OK && data != null) {
				try {
					int gameNo = Integer.parseInt(data.getAction());
					Cursor cursor = this.getScidAppContext().getGamesCursor();
					if (cursor == null) {
						cursor = this.getCursor();
					}
					if (cursor != null && cursor.moveToPosition(gameNo)) {
						startManagingCursor(cursor);
						setPgnFromCursor(cursor);
					}
				} catch (NumberFormatException nfe) {
					Toast.makeText(getApplicationContext(), R.string.invalid_number_format, Toast.LENGTH_SHORT).show();
				}
			}
			break;
		case RESULT_PGN_FILEDIALOG:
			// the result of the file dialog for the pgn import
			if (resultCode == RESULT_OK && data != null) {
				String pgnFileName = data.getAction();
				if (pgnFileName != null) {
					Tools.importPgn(this, pgnFileName, RESULT_PGN_FILE_IMPORT);
				}
			}
			break;
		case RESULT_PGN_FILE_IMPORT:
			// the result after importing the pgn file
			if (resultCode == RESULT_OK && data != null) {
				String pgnFileName = data.getAction();
				if (pgnFileName != null) {
					// open the successfully created scid database
					String scidFileName = Tools.stripExtension(pgnFileName) + ".si4";
					loadScidFile(scidFileName, 0);
				}
			}
			break;
		case RESULT_TWIC_IMPORT:
			// the result of the file dialog for the pgn import after TWIC
			// download
			// twic import has it's own result to delete the pgn file after
			// successful import
			if (resultCode == RESULT_OK && data != null) {
				String pgnFileName = data.getAction();
				if (pgnFileName != null) {
					Tools.importPgn(this, Tools.getFullScidFileName(pgnFileName), RESULT_PGN_IMPORT);
				}
			}
			break;
		case RESULT_PGN_IMPORT:
			// the result after importing the pgn file
			if (resultCode == RESULT_OK && data != null) {
				String pgnFileName = data.getAction();
				if (pgnFileName != null) {
					new File(pgnFileName).delete();
				}
				String scidFileName = Tools.stripExtension(pgnFileName) + ".si4";
				loadScidFile(scidFileName, 0);
			}
			break;
		case RESULT_ADD_ENGINE:
			if (resultCode == AddEngineActivity.RESULT_EXECUTABLE_EXISTS && data != null) {
				String engineName = data.getStringExtra(AddEngineActivity.DATA_ENGINE_NAME);
				String executable = data.getStringExtra(AddEngineActivity.DATA_ENGINE_EXECUTABLE);
				boolean makeCurrentEngine = data.getBooleanExtra(AddEngineActivity.DATA_MAKE_CURRENT_ENGINE, false);
				if (executable == null) {
					Toast.makeText(getApplicationContext(), getText(R.string.no_engine_selected), Toast.LENGTH_LONG).show();
				} else {
					addNewEngine(engineName, executable, makeCurrentEngine, false);
				}
			}
			break;
		case RESULT_REMOVE_ENGINE:
			if (resultCode == RESULT_OK && data != null) {
				final String _engineName = data.getStringExtra(RemoveEngineActivity.DATA_ENGINE_NAME);
				if (_engineName != null && _engineName.length() > 0) {
					// Update preferences if removing current analysis engine
					String analysisEngine = settings.getString("analysisEngine", null);
					if (analysisEngine != null && analysisEngine.equals(_engineName)) {
						final EngineManager.EngineChangeListener _listener = new EngineManager.EngineChangeListener() {

							@Override
							public void engineChanged(EngineChangeEvent event) {
								if (_engineName.equals(event.getEngineName()) && event.getChangeType() == EngineChangeEvent.REMOVE_ENGINE && event.getSuccess()) {
									Editor editor = settings.edit();
									editor.putString("analysisEngine", EngineManager.getDefaultEngine().getName());
									editor.commit();
								}
								engineManager.removeEngineChangeListener(this);
							}
						};
						engineManager.addEngineChangeListener(_listener);

					}
					engineManager.removeEngine(_engineName);
				}
			}
			break;
		case RESULT_SAVE_GAME:
			if (resultCode == RESULT_OK && data != null) {
				String gameNoString = data.getAction();
				if (gameNoString != null) {
					int gameNo = new Integer(gameNoString);
					if (gameNo == -1) {
						// a new game was added
						// TODO: reset cursor for now - saving should be done
						// within the
						// data provider and cursor
						Cursor cursor = getCursor();
						// move to newly added game
						if (cursor != null && cursor.moveToLast()) {
							setPgnFromCursor(cursor);
						}
					}
				}
			}
			break;
		}
	}

	private void loadScidFile(String fileName, int gameNo) {
		Editor editor = settings.edit();
		editor.putString("currentScidFile", fileName);
		editor.commit();
		getScidAppContext().setCurrentFileName(Tools.stripExtension(fileName));

		Cursor cursor = getCursor();
		if (cursor.moveToPosition(gameNo) || cursor.moveToFirst()) {
			setPgnFromCursor(cursor);
		} else {
			newGame();
		}
	}

	public void addNewEngine(String engineName, String executable, boolean makeCurrentEngine, boolean copied) {
		if (makeCurrentEngine) {
			final String _engineName = engineName;
			final EngineManager.EngineChangeListener _listener = new EngineManager.EngineChangeListener() {

				@Override
				public void engineChanged(EngineChangeEvent event) {
					if (_engineName.equals(event.getEngineName()) && event.getChangeType() == EngineChangeEvent.ADD_ENGINE && event.getSuccess()) {
						Editor editor = settings.edit();
						editor.putString("analysisEngine", _engineName);
						editor.commit();
						engineManager.setCurrentEngineName(_engineName);
					}
					engineManager.removeEngineChangeListener(this);
				}
			};
			engineManager.addEngineChangeListener(_listener);
		}
		engineManager.addEngine(engineName, executable);
	}

	private final void setBoardFlip() {
		// check player names
		boolean flipped = boardFlipped;
		if (autoSwapSides) {
			if (gameMode.analysisMode()) {
				flipped = !cb.pos.whiteMove;
			} else if (gameMode.playerWhite() && gameMode.playerBlack()) {
				flipped = !cb.pos.whiteMove;
			} else if (gameMode.playerWhite()) {
				flipped = false;
			} else if (gameMode.playerBlack()) {
				flipped = true;
			} else { // two computers
				flipped = !cb.pos.whiteMove;
			}
		}
		cb.setFlipped(flipped);
	}

	@Override
	public void setSelection(int sq) {
		cb.setSelection(sq);
	}

	@Override
	public void setFromSelection(int sq) {
		cb.setFromSelection(sq);
	}

	@Override
	public void setStatusString(final String str) {
		String prefix = "";
		if (getScidAppContext().isDeleted()) {
			prefix = "<font color='red'><b>DELETED</b></font> ";
		}
		status.setText(Html.fromHtml(prefix + str), TextView.BufferType.SPANNABLE);
	}

	@Override
	public void moveListUpdated() {
		if (gameMode.studyMode()) {
			moveList.setText("");
		} else if (!gameMode.analysisMode()) {
			if (pgnOptions.view.allMoves) {
				moveList.setText(gameTextListener.getSpannableData());
			} else {
				boolean whiteMove = false;
				Position position = this.getScidAppContext().getPosition();
				if (position != null) {
					whiteMove = !position.whiteMove;
				}
				moveList.setText(gameTextListener.getCurrentSpannableData(whiteMove));
			}
			Tools.bringPointtoView(moveList, moveListScroll, gameTextListener.getCurrentPosition());
		}
		if (gameTextListener.atEnd()) {
			moveListScroll.fullScroll(View.FOCUS_DOWN);
		}
	}

	@Override
	public void setPosition(Position pos, String variantInfo, List<Move> variantMoves) {
		variantStr = variantInfo;
		this.variantMoves = variantMoves;
		cb.setPosition(pos);
		((ScidApplication) getApplicationContext()).setPosition(pos);
		setBoardFlip();
		updateThinkingInfo();
	}

	private String thinkingStr = "";
	private String bookInfoStr = "";
	private String variantStr = "";
	private List<Move> pvMoves = null;
	private List<Move> bookMoves = null;
	private List<Move> variantMoves = null;

	@Override
	public void setThinkingInfo(String pvStr, String bookInfo, List<Move> pvMoves, List<Move> bookMoves) {
		thinkingStr = pvStr;
		bookInfoStr = bookInfo;
		this.pvMoves = pvMoves;
		this.bookMoves = bookMoves;
		updateThinkingInfo();
	}

	private final void updateThinkingInfo() {
		boolean thinkingEmpty = true;
		{
			String s = "";
			if (mShowThinking || gameMode.analysisMode()) {
				s = thinkingStr;
			}
			if (s.length() > 0) {
				thinkingEmpty = false;
				moveList.setText(s, TextView.BufferType.SPANNABLE);
			}
		}
		if (mShowBookHints && (bookInfoStr.length() > 0)) {
			String s = "";
			if (!thinkingEmpty) {
				s += "<br>";
			}
			s += "<b>Book:</b>" + bookInfoStr;
			moveList.append(Html.fromHtml(s));
			thinkingEmpty = false;
		}
		if (variantStr.indexOf(' ') >= 0 && !gameMode.studyMode()) {
			String s = "";
			if (!thinkingEmpty) {
				s += "<br>";
			}
			s += "<b>Var:</b> " + variantStr;
			moveList.append(Html.fromHtml(s));
		}

		List<Move> hints = null;
		if (!gameMode.studyMode()) {
			if (mShowThinking) {
				hints = pvMoves;
			}
			if ((variantMoves != null) && variantMoves.size() > 1) {
				hints = variantMoves;
			}
			if ((hints != null) && (hints.size() > maxNumArrows)) {
				hints = hints.subList(0, maxNumArrows);
			}
		}
		cb.setMoveHints(hints);
	}

	static final int SELECT_GOTO_GAME_DIALOG = 3;
	static final int IMPORT_PGN_DIALOG = 6;
	static final int MOVELIST_MENU_DIALOG = 9;

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case MOVELIST_MENU_DIALOG:
			MoveListDialog dialog = new MoveListDialog(this);
			return dialog.create(ctrl);
		case SELECT_GOTO_GAME_DIALOG:
			return createGotoGameDialog();
		case IMPORT_PGN_DIALOG:
			return createImportDialog();
		}
		return null;
	}

	private Dialog createGotoGameDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.goto_game_title);
		builder.setMessage(R.string.goto_game_number);
		final EditText input = new EditText(this);
		input.setInputType(InputType.TYPE_CLASS_NUMBER);
		builder.setView(input);
		builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) {
				try {
					int gameNo = Integer.parseInt(input.getText().toString()) - 1;
					Cursor cursor = getCursor();
					if (cursor != null && cursor.moveToPosition(gameNo)) {
						setPgnFromCursor(cursor);
					}
				} catch (NumberFormatException nfe) {
					Toast.makeText(getApplicationContext(), R.string.invalid_number_format, Toast.LENGTH_SHORT).show();
				}
			}
		});
		builder.setNegativeButton(android.R.string.cancel, null);
		AlertDialog alert = builder.create();
		return alert;
	}

	private AlertDialog createImportDialog() {
		final int IMPORT_PGN_FILE = 0;
		final int IMPORT_TWIC = 1;
		final int IMPORT_CHESSOK = 2;

		List<CharSequence> lst = new ArrayList<CharSequence>();
		List<Integer> actions = new ArrayList<Integer>();
		lst.add(getString(R.string.import_pgn_file));
		actions.add(IMPORT_PGN_FILE);
		lst.add(getString(R.string.import_twic));
		actions.add(IMPORT_TWIC);
		lst.add(getString(R.string.import_chessok));
		actions.add(IMPORT_CHESSOK);
		final List<Integer> finalActions = actions;
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.import_pgn_title);
		builder.setItems(lst.toArray(new CharSequence[lst.size()]), new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int item) {
				switch (finalActions.get(item)) {
				case IMPORT_PGN_FILE:
					importPgnFile();
					break;
				case IMPORT_TWIC:
					importTwic();
					break;
				case IMPORT_CHESSOK:
					importChessOk();
					break;
				}
			}
		});
		AlertDialog alert = builder.create();
		return alert;
	}

	private void newGame() {
		updateMenu();
		getScidAppContext().setCurrentGameNo(-1);
		saveCurrentGameNo();
		ctrl.newGame(gameMode);
		getScidAppContext().setFavorite(false);
		getScidAppContext().setDeleted(false);
		ctrl.setGuiPaused(true);
		ctrl.setGuiPaused(false);
		ctrl.startGame();
		setFav();
	}

	private void saveCurrentGameNo() {
		Editor editor = settings.edit();
		editor.putInt("currentGameNo", this.getScidAppContext().getCurrentGameNo());
		editor.commit();
	}

	private void updateFavoriteFlag(boolean value, String successMsg, String failureMsg) {
		if (getScidAppContext().getCurrentFileName().length() > 0) {
			int updated = setFavorite(value);
			String message;
			if (updated > 0) {
				message = successMsg;
				reloadCursor();
				getScidAppContext().setFavorite(value);
				setFav();
				reloadGameList = true;
			} else {
				message = failureMsg;
			}
			Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
		}
	}

	private int setFavorite(boolean isFavorite) {
		ContentValues values = new ContentValues();
		values.put("isFavorite", isFavorite);
		return updateGame(values);
	}

	private int updateGame(ContentValues values) {
		Uri uri = Uri.parse("content://org.scid.database.scidprovider/games/" + getScidAppContext().getCurrentGameNo());
		String where = getScidAppContext().getCurrentFileName();
		int updated = getContentResolver().update(uri, values, where, null);
		return updated;
	}

	private void resetFilter() {
		final String fileName = getScidAppContext().getCurrentFileName();
		if (fileName.length() != 0) {
			Cursor cursor = getCursor();
			if (cursor != null) {
				cursor.moveToPosition(getScidAppContext().getCurrentGameNo());
			}
		} else {
			getScidAppContext().setGamesCursor(null);
		}
	}

	private void importPgnFile() {
		Intent i = new Intent(ScidAndroidActivity.this, SelectFileActivity.class);
		i.setAction(".pgn");
		startActivityForResult(i, RESULT_PGN_FILEDIALOG);
	}

	private void importTwic() {
		Intent i = new Intent(ScidAndroidActivity.this, ImportTwicActivity.class);
		startActivityForResult(i, RESULT_TWIC_IMPORT);
	}

	private void importChessOk() {
		Intent i = new Intent(ScidAndroidActivity.this, ImportChessOkActivity.class);
		startActivityForResult(i, RESULT_TWIC_IMPORT);
	}

	private Cursor getCursor() {
		final String currentScidFile = settings.getString("currentScidFile", "");
		if (currentScidFile.length() == 0) {
			return null;
		}
		String scidFileName = Tools.stripExtension(currentScidFile);
		Cursor cursor = getContentResolver().query(Uri.parse("content://org.scid.database.scidprovider/games"), null, scidFileName, null, null);
		((ScidApplication) this.getApplicationContext()).setGamesCursor(cursor);
		((ScidApplication) this.getApplicationContext()).setNoGames(cursor);

		startManagingCursor(cursor);
		return cursor;
	}

	private void reloadCursor() {
		final String currentScidFile = settings.getString("currentScidFile", "");
		if (currentScidFile.length() == 0) {
			return;
		}
		String scidFileName = Tools.stripExtension(currentScidFile);
		Cursor cursor = getContentResolver().query(Uri.parse("content://org.scid.database.scidprovider/games"), null, scidFileName, null, null);

		cursor.moveToPosition(getScidAppContext().getCurrentGameNo());

		getScidAppContext().setGamesCursor(cursor);
		getScidAppContext().setNoGames(cursor);

		startManagingCursor(cursor);
	}

	@Override
	public void reportInvalidMove(Move m) {
		String msg = "";
		if (gameMode.studyMode()) {
			msg = String.format(getString(R.string.wrong_move), TextIO.squareToString(m.from), TextIO.squareToString(m.to));
		} else {
			msg = String.format(getString(R.string.invalid_move), TextIO.squareToString(m.from), TextIO.squareToString(m.to));
		}
		Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
	}

	@Override
	public void runOnUIThread(Runnable runnable) {
		runOnUiThread(runnable);
	}

	@Override
	public void setGameInformation(String white, String black, String gameNo) {
		if (!gameMode.studyMode()) {
			flipBoardForPlayerNames(white, black);
		}
		if (whitePlayer != null) {
			whitePlayer.setText(white);
			blackPlayer.setText(black);
			this.gameNo.setText(gameNo);
		} else {
			setTitle(gameNo + "   " + white + " - " + black);
		}
	}

	public ScidApplication getScidAppContext() {
		return (ScidApplication) getApplicationContext();
	}

	/** Report a move made that is a candidate for GUI animation. */
	public void setAnimMove(Position sourcePos, Move move, boolean forward) {
		if (move != null) {
			cb.setAnimMove(sourcePos, move, forward);
		}
	}

	@Override
	public void clipboardChanged() {
		updateMenu();
	}

	@Override
	public void downloadSuccess(File pgnFile) {
		Tools.importPgnFile(ScidAndroidActivity.this, pgnFile, RESULT_PGN_IMPORT);
	}

	@Override
	public void downloadFailure(String message) {
		Tools.showErrorMessage(this, this.getText(R.string.download_error) + " (" + message + ")");
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		getMenuInflater().inflate(R.menu.movelist_context_menu, menu);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.export_game_to_a_file_item: {
			Intent i = new Intent(ScidAndroidActivity.this, ExportPgnToFileActivity.class);
			startActivity(i);
			break;
		}
		case R.id.share_game_item: {
			String pgn = getScidAppContext().getController().getPGN();

			File scidFileDir = new File(Environment.getExternalStorageDirectory() + File.separator + SCID_DIRECTORY + File.separator + "tmp");
			File pgnFile = new File(Environment.getExternalStorageDirectory() + File.separator + SCID_DIRECTORY + File.separator + "tmp" + File.separator + getScidAppContext().getController().getFileName() + ".pgn");

			if (!pgnFile.exists()) {
				if (!scidFileDir.exists()) {
					scidFileDir.mkdirs();
				}

				try {
					FileWriter fw = new FileWriter(pgnFile);
					fw.append(pgn);
					fw.flush();
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			Uri uri = Uri.fromFile(pgnFile);

			Intent sendIntent = new Intent(Intent.ACTION_SEND);
			sendIntent.setType("text/plain");
			sendIntent.putExtra(Intent.EXTRA_SUBJECT, "LearnChess shared game");
			sendIntent.putExtra(Intent.EXTRA_TEXT, getScidAppContext().getController().getMailText());
			sendIntent.putExtra(Intent.EXTRA_STREAM, uri);

			startActivity(Intent.createChooser(sendIntent, "Share game by:"));

			break;
		}
		case R.id.open_game_in_droidfish_item: {
			String pgn = getScidAppContext().getController().getPGN();

			File scidTmpDir = new File(Environment.getExternalStorageDirectory() + File.separator + SCID_DIRECTORY + File.separator + "tmp");
			File pgnFile = new File(Environment.getExternalStorageDirectory() + File.separator + SCID_DIRECTORY + File.separator + "tmp" + File.separator + getScidAppContext().getController().getFileName() + ".pgn");

			if (!pgnFile.exists()) {
				if (!scidTmpDir.exists()) {
					scidTmpDir.mkdirs();
				}

				try {
					FileWriter fw = new FileWriter(pgnFile);
					fw.append(pgn);
					fw.flush();
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			Uri uri = Uri.fromFile(pgnFile);

//			Intent sendIntent = new Intent(Intent.ACTION_VIEW);
//			sendIntent.setType("application/x-chess-pgn");
//			sendIntent.putExtra(Intent.EXTRA_fSTREAM, uri);
			
			Intent sendIntent = new Intent(Intent.ACTION_VIEW);
			sendIntent.setDataAndType(uri, "application/x-chess-pgn");

			startActivity(Intent.createChooser(sendIntent, "Share game by:"));

			break;
		}
		}
		return true;
	}

	@Override
	public void requestPromotePiece() {
		// TODO Think to remove this method from interface
	}

	public void onFinishStartAnalysis() {
		// TODO Think to remove this method
	}

	public static class GestureListener implements OnTouchListener {

		public static interface OnSwipeListener {

			public void onSwipe();

		}

		private static final int SWIPE_MIN_DISTANCE = 120;
		private static final int SWIPE_THRESHOLD_VELOCITY = 200;

		private GestureDetector gestureDetector;
		private OnSwipeListener onSwipeListener;

		public GestureListener(Context context, OnSwipeListener onSwipeListener) {
			this.onSwipeListener = onSwipeListener;

			gestureDetector = new GestureDetector(context, new SimpleOnGestureListener() {
				@Override
				public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
					try {
						float x1 = e1.getX();
						float y1 = e1.getY();
						float x2 = e2.getX();
						float y2 = e2.getY();

						double path = Math.hypot(Math.abs(x2 - x1), Math.abs(y2 - y1));

						if (path > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
							if (GestureListener.this.onSwipeListener != null) {
								GestureListener.this.onSwipeListener.onSwipe();
							}
						}
					} catch (Exception e) {
						// nothing
					}
					return false;
				}
			});
		}

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			return gestureDetector.onTouchEvent(event);
		}

	}

}
